package com.cobra.activiti.controller;

import com.cobra.activiti.enums.ProcessInstanceFinishEnum;
import com.cobra.activiti.pojo.param.*;
import com.cobra.activiti.pojo.vo.PageVO;
import com.cobra.activiti.pojo.vo.ProcessInstanceVO;
import com.cobra.activiti.response.ResultVOUtil;
import com.cobra.activiti.response.ReturnValueLoader;
import com.cobra.activiti.utils.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author yaobin
 * @date 2020/4/21 0021 10:17
 * @Description 流程实例vo
 */
@RestController
@Slf4j
@RequestMapping("/processInstance")
public class ProcessInstanceController {

    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private HistoryService historyService;

    @Autowired
    private IdentityService identityService;

    @Autowired
    private TaskService taskService;


    /**
     * 开启流程实例
     *
     * @return
     */
    @PostMapping("/start")
    public ReturnValueLoader startTask(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                       @Valid @RequestBody TaskStartParam requestParam) {

        String processDefinitionKey = requestParam.getProcessDefinitionKey();
        String businessKey = requestParam.getBusinessKey();
        String name = requestParam.getName();
        String userId = requestParam.getUserId();

        long count = historyService.createHistoricTaskInstanceQuery().processInstanceBusinessKey(businessKey).count();

        if (count > 0) {
            return ResultVOUtil.error("该申请已经提交，请勿重复提交！");
        }

        //设置发起人（实现与线程有关），用于查询流程发起人的条件
        identityService.setAuthenticatedUserId(userId);
        //设置业务key和使用的流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey);
        String instanceId = processInstance.getId();
        //设置流程实例的name
        runtimeService.setProcessInstanceName(instanceId, name);

        Task task = taskService.createTaskQuery().
                processInstanceBusinessKeyLike(businessKey).singleResult();

        if (task == null) {
            return ResultVOUtil.success("代办任务不存在或已处理，请重新刷新列表确认！");
        }
        //设定第一个节点任务的处理人
        taskService.setOwner(task.getId(), userId);

        return ResultVOUtil.success("开启流程成功！");
    }

    /**
     * 查询所有流程实例
     *
     * @param requestParam
     * @return
     */
    @PostMapping("/getAllHistoryProcesses")
    public ReturnValueLoader<PageVO<ProcessInstanceVO>> getAllHistoryProcesses(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                                                               @Valid @RequestBody ProcessInstanceSelectListParam requestParam) {

        PageVO<ProcessInstanceVO> result = new PageVO<>();
        Integer current = requestParam.getCurrent();
        Integer queryPage = current - 1;
        Integer size = requestParam.getSize();
        String isFinish = requestParam.getIsFinish();

        Long count = 0L;
        Integer intCount = 0;
        List<HistoricProcessInstance> historicProcessInstanceList = new ArrayList<>(size);

        if (ProcessInstanceFinishEnum.FINISHED.getMessage().equals(isFinish)) {
            count = historyService.createHistoricProcessInstanceQuery().finished().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().finished()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);
        } else if (ProcessInstanceFinishEnum.UNFINISHED.getMessage().equals(isFinish)) {
            count = historyService.createHistoricProcessInstanceQuery().unfinished().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().unfinished()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);
        } else {
            count = historyService.createHistoricProcessInstanceQuery().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);
        }

        return getPageVOReturnValueLoader(result, current, size, intCount, historicProcessInstanceList);

    }

    /**
     * 查询某个流程key的流程实例
     *
     * @param requestParam
     * @return
     */
    @PostMapping("/getHistoryProcessesByProcessKey")
    public ReturnValueLoader<PageVO<ProcessInstanceVO>> getHistoryProcessesByProcessKey(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                                                                        @Valid @RequestBody ProcessInstanceListByKeyParam requestParam) {
        String processKey = requestParam.getProcessKey();
        PageVO<ProcessInstanceVO> result = new PageVO<>();
        Integer current = requestParam.getCurrent();
        Integer queryPage = current - 1;
        Integer size = requestParam.getSize();
        String isFinish = requestParam.getIsFinish();

        Long count = 0L;
        Integer intCount = 0;
        List<HistoricProcessInstance> historicProcessInstanceList = new ArrayList<>(size);

        if (ProcessInstanceFinishEnum.FINISHED.getMessage().equals(isFinish)) {

            count = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processKey).finished().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processKey).finished()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);

        } else if (ProcessInstanceFinishEnum.UNFINISHED.getMessage().equals(isFinish)) {

            count = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processKey).unfinished().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processKey).unfinished()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);

        } else {
            count = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processKey).count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().processDefinitionKey(processKey)
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);
        }

        return getPageVOReturnValueLoader(result, current, size, intCount, historicProcessInstanceList);
    }

    /**
     * 查询某人发起的流程实例
     *
     * @param requestParam
     * @return
     */
    @PostMapping("/getHistoryProcessesByStartUser")
    public ReturnValueLoader<PageVO<ProcessInstanceVO>> getHistoryProcessesByStartUser(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                                                                       @Valid @RequestBody ProcessInstanceListByStartUserIdParam requestParam) {

        String userId = requestParam.getUserId();
        PageVO<ProcessInstanceVO> result = new PageVO<>();
        Integer current = requestParam.getCurrent();
        Integer queryPage = current - 1;
        Integer size = requestParam.getSize();
        String isFinish = requestParam.getIsFinish();

        Long count = 0L;
        Integer intCount = 0;
        List<HistoricProcessInstance> historicProcessInstanceList = new ArrayList<>(size);

        if (ProcessInstanceFinishEnum.FINISHED.getMessage().equals(isFinish)) {

            count = historyService.createHistoricProcessInstanceQuery().startedBy(userId).finished().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().startedBy(userId).finished()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);

        } else if (ProcessInstanceFinishEnum.UNFINISHED.getMessage().equals(isFinish)) {

            count = historyService.createHistoricProcessInstanceQuery().startedBy(userId).unfinished().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().startedBy(userId).unfinished()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);

        } else {
            count = historyService.createHistoricProcessInstanceQuery().startedBy(userId).count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().startedBy(userId)
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);
        }

        return getPageVOReturnValueLoader(result, current, size, intCount, historicProcessInstanceList);
    }

    /**
     * 查询某人参与过的流程实例
     *
     * @param requestParam
     * @return
     */
    @PostMapping("/getHistoryProcessesByInvolvedUser")
    public ReturnValueLoader<PageVO<ProcessInstanceVO>> getHistoryProcessesByInvolvedUser(//@ApiParam(name = "receiveSwitchUpdateRequestVO", value = "json格式", required = true)
                                                                                          @Valid @RequestBody ProcessInstanceListByInvolvedUserIdParam requestParam) {

        String userId = requestParam.getUserId();
        PageVO<ProcessInstanceVO> result = new PageVO<>();
        Integer current = requestParam.getCurrent();
        Integer queryPage = current - 1;
        Integer size = requestParam.getSize();
        String isFinish = requestParam.getIsFinish();

        Long count = 0L;
        Integer intCount = 0;
        List<HistoricProcessInstance> historicProcessInstanceList = new ArrayList<>(size);

        if (ProcessInstanceFinishEnum.FINISHED.getMessage().equals(isFinish)) {

            count = historyService.createHistoricProcessInstanceQuery().involvedUser(userId).finished().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().involvedUser(userId).finished()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);

        } else if (ProcessInstanceFinishEnum.UNFINISHED.getMessage().equals(isFinish)) {

            count = historyService.createHistoricProcessInstanceQuery().involvedUser(userId).unfinished().count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().involvedUser(userId).unfinished()
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);

        } else {
            count = historyService.createHistoricProcessInstanceQuery().involvedUser(userId).count();
            intCount = count.intValue();
            historicProcessInstanceList = historyService.createHistoricProcessInstanceQuery().involvedUser(userId)
                    .orderByProcessInstanceStartTime()
                    .desc().listPage(queryPage, size);
        }

        return getPageVOReturnValueLoader(result, current, size, intCount, historicProcessInstanceList);
    }

    /**
     * 组装返回分页信息
     *
     * @param result
     * @param current
     * @param size
     * @param intCount
     * @param historicProcessInstanceList
     * @return
     */
    private ReturnValueLoader<PageVO<ProcessInstanceVO>> getPageVOReturnValueLoader(PageVO<ProcessInstanceVO> result, Integer current, Integer size, Integer intCount, List<HistoricProcessInstance> historicProcessInstanceList) {
        List<ProcessInstanceVO> processInstanceVOList = historicProcessInstanceList.stream().map(historicProcessInstance -> {
            ProcessInstanceVO processInstanceVO = new ProcessInstanceVO();
            processInstanceVO.setId(historicProcessInstance.getId());
            processInstanceVO.setName(historicProcessInstance.getName());
            processInstanceVO.setBusinessKey(historicProcessInstance.getBusinessKey());
            processInstanceVO.setStartTime(historicProcessInstance.getStartTime());
            processInstanceVO.setEndTime(historicProcessInstance.getEndTime());
            processInstanceVO.setDuration(DateUtil.getTimeDiffStr(historicProcessInstance.getDurationInMillis()));
            return processInstanceVO;
        }).collect(Collectors.toList());

        result.setRecords(processInstanceVOList);
        result.setTotal(intCount);
        result.setSize(size);
        result.setCurrent(current);
        return ResultVOUtil.success(result);
    }

}
